package com.woniuxy.order.service.impl;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.ObjectUtil;
import com.woniuxy.order.entity.OrderWaste;
import com.woniuxy.order.entity.WasteType;
import com.woniuxy.order.mapper.OrderWasteMapper;
import com.woniuxy.order.mapper.WasteTypeMapper;
import com.woniuxy.order.rabbitMQ.RabbitMQConfig;
import com.woniuxy.permission.entity.Permission;
import com.woniuxy.permission.mapper.PermissionMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.woniuxy.merchant.entity.Site;
import com.woniuxy.merchant.mapper.SiteMapper;
import com.woniuxy.order.entity.OrderInfo;
import com.woniuxy.order.mapper.OrderInfoMapper;
import com.woniuxy.order.service.IOrderInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniuxy.user.entity.UserInfo;
import com.woniuxy.user.mapper.UserInfoMapper;
import org.json.JSONObject;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import zsd.waste.dto.OrderInfoDto;
import zsd.waste.form.*;
import org.springframework.amqp.core.Message;

import org.json.JSONObject;
import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author author
 * @since 2025-05-13
 */
@Service
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements IOrderInfoService {

    @Resource
    private OrderInfoMapper orderInfoMapper;
    @Resource
    private SiteMapper siteMapper;

    @Resource
    private UserInfoMapper userInfoMapper;

    @Resource
    private OrderLogServiceImpl orderLogService;

    @Resource
    private PermissionMapper permissionMapper;

    @Resource
    private RabbitTemplate rabbitTemplate;

    @Resource
    private WasteTypeMapper wasteTypeMapper;

    @Resource
    private OrderWasteMapper orderWasteMapper;

    @Value("${amap.api.key}")
    private String amapKey;

    private static final int HTTP_TIMEOUT = 5000; // 5秒超时


    // 提取获取经纬度的公共方法
    private double[] getGeoLocation(String address) throws Exception {
        String encodedAddress = URLEncoder.encode(address, "UTF-8");
        String urlStr = "https://restapi.amap.com/v3/geocode/geo?address=" + encodedAddress + "&key=" + amapKey;

        HttpURLConnection connection = (HttpURLConnection) new URL(urlStr).openConnection();
        connection.setRequestMethod("GET");
        connection.setConnectTimeout(HTTP_TIMEOUT);
        connection.setReadTimeout(HTTP_TIMEOUT);

        try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
            JSONObject jsonResponse = new JSONObject(reader.lines().collect(Collectors.joining()));
            if ("1".equals(jsonResponse.getString("status")) && jsonResponse.getInt("count") > 0) {
                String location = jsonResponse.getJSONArray("geocodes").getJSONObject(0).getString("location");
                String[] latLon = location.split(",");
                return new double[]{
                        Double.parseDouble(latLon[0]), // 经度
                        Double.parseDouble(latLon[1])  // 纬度
                };
            }
            throw new Exception("无法获取地址的经纬度信息");
        } catch (IOException e) {
            throw new Exception("获取经纬度请求失败: " + e.getMessage());
        }
    }




    /**
     * 用户发起订单，填写基本信息并且填入废品信息集合，填入数据后查询用户地址经纬度，再查询所有站点位置经纬度
     *将用户经纬度与站点经纬度做比较计算距离后，将距离最近的三个站点放入集合,依次放入消息队列设置15分钟过期时间，到期后分配给下一个站点加入站点ID，继续等待十五分钟，三个站点十五分钟都过期后，删除关联的站点ID，超级管理员强制分配
     * @return
     */
    @Override
    public OrderInfo createOrder(CreateOrderForm form) throws Exception {
        // 添加表单验证
        if (form == null) {
            throw new IllegalArgumentException("订单表单不能为空");
        }
        if (form.getWasteInfos() == null || form.getWasteInfos().isEmpty()) {
            throw new IllegalArgumentException("废品信息列表不能为空");
        }

        OrderInfo orderInfo = new OrderInfo();
        WasteType wasteType = null;
        try {
            wasteType = wasteTypeMapper.selectById(form.getWasteInfos().get(0).getSasteTypeId());
            if (wasteType == null) {
                throw new RuntimeException("未找到对应的废品类型，请检查废品类型ID是否正确");
            }
        } catch (Exception e) {
            throw new RuntimeException("查询废品类型失败: " + e.getMessage());
        }

        // 1. 获取用户地址经纬度
        double[] userLocation;
        try {
            userLocation = getGeoLocation(form.getUserAddress());
        } catch (Exception e) {
            throw new RuntimeException("获取用户地址经纬度失败: " + e.getMessage());
        }
        double userLon = userLocation[0];
        double userLat = userLocation[1];

        // 2. 查询所有站点
        List<Site> sites = siteMapper.selectList(new QueryWrapper<>());
        if (sites == null || sites.isEmpty()) {
            throw new RuntimeException("系统中暂无可用站点，请联系管理员");
        }

        // 3. 批量获取站点经纬度并计算距离，选择最近的3个站点
        List<Site> nearestSites = sites.parallelStream()
                .map(site -> {
                    try {
                        double[] siteLocation = getGeoLocation(site.getSiteAddress());
                        double distance = calculateDistance(userLat, userLon, siteLocation[1], siteLocation[0]);
                        return new AbstractMap.SimpleEntry<>(site, distance);
                    } catch (Exception e) {
                        return null;
                    }
                })
                .filter(Objects::nonNull)
                .sorted(Comparator.comparingDouble(AbstractMap.SimpleEntry::getValue))
                .limit(3)
                .map(AbstractMap.SimpleEntry::getKey)
                .collect(Collectors.toList());

        if (nearestSites.isEmpty()) {
            throw new Exception("没有可用的站点");
        }

        // 4. 创建订单
        Snowflake snowflake = new Snowflake(1, 1);
        orderInfo.setUserId(form.getUserId());
        orderInfo.setUserName(form.getUserName());
        orderInfo.setUserPhone(form.getUserPhone());
        orderInfo.setUserAddress(form.getUserAddress());
        orderInfo.setSiteId(nearestSites.get(0).getId()); // 先分配给最近的站点
        orderInfo.setCreatTime(LocalDateTime.now());
        orderInfo.setOrderNumber(snowflake.nextIdStr());
        orderInfo.setOrderState(1);
        orderInfo.setStartTime(form.getStartTime());
        orderInfo.setRemarks(form.getRemarks());
        orderInfo.setLon(String.valueOf(userLon));
        orderInfo.setLat(String.valueOf(userLat));

        // 发送延迟消息给第一个站点
        rabbitTemplate.convertAndSend(
                RabbitMQConfig.ORDER_DELAY_QUEUE,
                orderInfo.getOrderNumber(),
                message -> {
                    message.getMessageProperties().setHeader("currentSiteIndex", 0);
                    message.getMessageProperties().setHeader("nearestSiteIds",
                            nearestSites.stream().map(Site::getId).collect(Collectors.toList()));
                    message.getMessageProperties().setExpiration("900000"); // 15分钟 = 900000毫秒
                    return message;
                }
        );

        UserInfo userInfo = userInfoMapper.selectById(form.getUserId());

        orderInfoMapper.insert(orderInfo);

        // 添加订单废品信息集合
        for (WasteInfoInsert wasteInfo : form.getWasteInfos()) {
            OrderWaste orderWaste = new OrderWaste();
            orderWaste.setOrderNum(orderInfo.getOrderNumber());
            orderWaste.setWasteImage(wasteInfo.getWasteImage());
            orderWaste.setWasteInfo(wasteInfo.getWasteInfo());
            orderWaste.setWeight(wasteInfo.getWeight());
            orderWaste.setUnit(wasteType.getPriceUtil());
            orderWaste.setSasteTypeId(wasteInfo.getSasteTypeId());
            orderWaste.setSastePrice(wasteType.getPrice());
            orderWaste.setSasteAllPrice(wasteType.getPrice() * wasteInfo.getWeight());
            orderWasteMapper.insert(orderWaste);
        }

        // 记录日志
        orderLogService.logUserAction("用户下单", userInfo.getNickName(), orderInfo.getOrderId());
        return orderInfo;
    }


    // 添加消息消费者
    @RabbitListener(queues = RabbitMQConfig.ORDER_DELAY_QUEUE)
    public void processExpiredOrder(Message message) {
        String orderNumber = new String(message.getBody());
        Integer currentSiteIndex = message.getMessageProperties().getHeader("currentSiteIndex");
        List<Integer> nearestSiteIds = message.getMessageProperties().getHeader("nearestSiteIds");

        OrderInfo orderInfo = orderInfoMapper.selectOne(new QueryWrapper<OrderInfo>()
                .eq("order_number", orderNumber));

        if (orderInfo != null && orderInfo.getOrderState() == 1) {
            if (currentSiteIndex < nearestSiteIds.size() - 1) {
                // 分配给下一个站点
                orderInfo.setSiteId(nearestSiteIds.get(currentSiteIndex + 1));
                orderInfoMapper.updateById(orderInfo);

                // 再次发送延迟消息
                rabbitTemplate.convertAndSend(
                        RabbitMQConfig.ORDER_DELAY_QUEUE,
                        orderNumber,
                        nextMessage -> {
                            nextMessage.getMessageProperties().setHeader("currentSiteIndex", currentSiteIndex + 1);
                            nextMessage.getMessageProperties().setHeader("nearestSiteIds", nearestSiteIds);
                            nextMessage.getMessageProperties().setExpiration("900000");
                            return nextMessage;
                        }
                );
            } else {
                // 所有站点都已过期，删除站点关联
                orderInfo.setSiteId(null);
                orderInfoMapper.updateById(orderInfo);
            }
        }
    }





    @Override
    public List<OrderInfoDto> findMyOrder(Integer userId,Integer pageNum,Integer pageSize) throws Exception {
        if (userId == null) {
            throw new IllegalArgumentException("用户ID不能为空");
        }

        QueryWrapper<OrderInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId)
                .orderByDesc("creat_time"); // 按创建时间降序排列

        return orderInfoMapper.selectList(queryWrapper)
                .stream()
                .filter(Objects::nonNull) // 过滤空订单
                .map(orderInfo -> {
                    OrderInfoDto dto = new OrderInfoDto();
                    try {
                        Site site = siteMapper.selectById(orderInfo.getSiteId());
                        if (site != null) {
                            dto.setSiteName(site.getSiteName());
                        }

                        // 设置订单信息
                        dto.setCreatTime(orderInfo.getCreatTime());
                        dto.setOrderNumber(orderInfo.getOrderNumber());
                        dto.setWorkName(orderInfo.getWorkName());
                        dto.setWorkPhone(orderInfo.getWorkPhone());
                        dto.setRemarks(orderInfo.getRemarks());
                        dto.setStartTime(orderInfo.getStartTime());
                        dto.setUserAddress(orderInfo.getUserAddress());
                        dto.setUserName(orderInfo.getUserName());
                        dto.setUserPhone(orderInfo.getUserPhone());
                        dto.setOrderState(orderInfo.getOrderState());

                        UserInfo userInfo = userInfoMapper.selectById(userId);
                        // 记录日志
                        orderLogService.logUserAction("用户查询自己的订单",userInfo.getNickName(),orderInfo.getOrderId());

                        return dto;
                    } catch (Exception e) {
                        return null;
                    }
                })
                .filter(Objects::nonNull) // 过滤处理异常的订单
                .collect(Collectors.toList());
    }





    @Override
    public List<OrderInfoDto> findAllOrder(FindAllOrderFrom findAllOrderFrom) throws Exception {

        QueryWrapper<OrderInfo> queryWrapper = new QueryWrapper<>();
        if (ObjectUtil.isNotEmpty(findAllOrderFrom.getUserName())) {
            queryWrapper.likeRight("user_name", findAllOrderFrom.getUserName());
        }
        if (findAllOrderFrom.getOrderNumber() != null) {
            queryWrapper.eq("order_number", findAllOrderFrom.getOrderNumber());
        }
        if (findAllOrderFrom.getSiteId() != null) {
            queryWrapper.eq("site_id", findAllOrderFrom.getSiteId()); // 修复bug
        }
        if (findAllOrderFrom.getOrderState() != null) {
            queryWrapper.eq("order_state", findAllOrderFrom.getOrderState());
        }
        queryWrapper.orderByDesc("creat_time"); // 添加默认排序

        return orderInfoMapper.selectList(queryWrapper)
                .stream()
                .filter(Objects::nonNull)
                .map(orderInfo -> {
                    OrderInfoDto dto = new OrderInfoDto();
                    Site site = siteMapper.selectById(orderInfo.getSiteId());

                    // 设置订单信息
                    dto.setCreatTime(orderInfo.getCreatTime());
                    dto.setOrderNumber(orderInfo.getOrderNumber());
                    dto.setWorkName(orderInfo.getWorkName());
                    dto.setWorkPhone(orderInfo.getWorkPhone());
                    dto.setRemarks(orderInfo.getRemarks());
                    dto.setSiteName(site != null ? site.getSiteName() : null);
                    dto.setStartTime(orderInfo.getStartTime());
                    dto.setUserAddress(orderInfo.getUserAddress());
                    dto.setUserName(orderInfo.getUserName());
                    dto.setUserPhone(orderInfo.getUserPhone());


                    // 记录日志
                    orderLogService.logUserAction("管理员查询条件查询订单","管理员",orderInfo.getOrderId());

                    return dto;
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<OrderInfoDto> findSiteOrder(FindSiteOrderFrom findSiteOrderFrom,Integer userId) throws Exception {
        if (userId == null) {
            throw new IllegalArgumentException("用户ID不能为空");
        }
        List<OrderInfoDto> orderInfoDtoList = new ArrayList<>();
        Permission permission = permissionMapper.selectById(userId);
        Site site = siteMapper.selectById(permission.getSiteId());
        QueryWrapper<OrderInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("site_id", site.getId());
        List<OrderInfo> list = orderInfoMapper.selectList(queryWrapper);
        if(list!=null){

            for (OrderInfo orderInfo : list) {

                OrderInfoDto orderInfoDto = new OrderInfoDto();

                orderInfoDto.setCreatTime(orderInfo.getCreatTime());

                orderInfoDto.setOrderNumber(orderInfo.getOrderNumber());

                orderInfoDto.setWorkName(orderInfo.getWorkName());

                orderInfoDto.setWorkPhone(orderInfo.getWorkPhone());

                orderInfoDto.setRemarks(orderInfo.getRemarks());

                orderInfoDto.setSiteName(site.getSiteName());

                orderInfoDto.setStartTime(orderInfo.getStartTime());

                orderInfoDto.setUserAddress(orderInfo.getUserAddress());

                orderInfoDto.setUserName(orderInfo.getUserName());

                orderInfoDto.setUserPhone(orderInfo.getUserPhone());

                orderInfoDto.setOrderState(orderInfo.getOrderState());

                // 记录日志
                orderLogService.logUserAction("站点根据条件查询自己订单",permission.getName(),orderInfo.getOrderId());


                orderInfoDtoList.add(orderInfoDto);

            }

        }
        return orderInfoDtoList;
    }

    @Override
    public void siteOrder(SiteOrderForm wof, String adminId) throws Exception {
        OrderInfo orderInfo = orderInfoMapper.selectById(wof.getOrderId());
        if (orderInfo==null){
            System.out.println("订单不存在");
        }
        Site site = siteMapper.selectById(wof.getSiteId());
        if (site.getStatus()==0){
            System.out.println("站点状态异常");
        }
        orderInfo.setOrderState(2);
        orderInfo.setSiteId(wof.getSiteId());
        orderInfo.setDirectorName(site.getSiteName());
        orderInfo.setDirectorPhone(site.getSiteUserPhone());
        orderInfoMapper.updateById(orderInfo);
    }

    @Override
    public void workOrder(WorkOrderForm form,Integer userId) throws Exception {
        Permission permission =permissionMapper.selectById(userId);
        Permission permission1 = permissionMapper.selectById(form.getWorkId());
        OrderInfo orderInfo = orderInfoMapper.selectById(form.getOrderId());
        if (orderInfo.getSiteId()!=permission.getSiteId()){
            System.out.println("该订单不属于该站点");
        }
        if (permission.getDelet()==1||permission.getState()==1){
            System.out.println("账户异常，无法分配");
        }
        if (orderInfo==null){
            System.out.println("订单不存在");
        }
        orderInfo.setWorkId(form.getWorkId());
        orderInfo.setWorkName(permission1.getName());
        orderInfo.setWorkPhone(permission1.getPhone());
        orderInfo.setOrderState(3);
        orderInfoMapper.updateById(orderInfo);

    }

    @Override
    public void confirmOrder(String orderNumber, Integer id) throws Exception {
        OrderInfo orderInfo = orderInfoMapper.selectOne(new QueryWrapper<OrderInfo>()
                .eq("order_number", orderNumber));
        Permission permission = permissionMapper.selectById(id);

        if (orderInfo == null) {
            throw new RuntimeException("订单不存在");
        }

        if (!orderInfo.getSiteId().equals(permission.getSiteId())) {
            throw new RuntimeException("该订单不属于当前站点");
        }

        // 更新订单状态为已接单(4)
        orderInfo.setOrderState(2);
        orderInfoMapper.updateById(orderInfo);

        // 取消所有未处理的延迟消息
        cancelPendingOrderMessages(orderNumber);

        // 记录日志
        Site site = siteMapper.selectById(permission.getSiteId());
        orderLogService.logUserAction("站点确认接单", site.getSiteName(), orderInfo.getOrderId());
    }

    @Override
    public List<OrderInfoDto> temporaryOrderInfo(Integer id, Integer pageNum, Integer pageSize) throws Exception {
        if (id == null) {
            throw new IllegalArgumentException("用户ID不能为空");
        }

        QueryWrapper<OrderInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("work_id", id)
                .orderByDesc("creat_time"); // 按创建时间降序排列

        return orderInfoMapper.selectList(queryWrapper)
                .stream()
                .filter(Objects::nonNull) // 过滤空订单
                .map(orderInfo -> {
                    OrderInfoDto dto = new OrderInfoDto();
                    try {
                        Site site = siteMapper.selectById(orderInfo.getSiteId());
                        if (site != null) {
                            dto.setSiteName(site.getSiteName());
                        }

                        // 设置订单信息
                        dto.setCreatTime(orderInfo.getCreatTime());
                        dto.setOrderNumber(orderInfo.getOrderNumber());
                        dto.setWorkName(orderInfo.getWorkName());
                        dto.setWorkPhone(orderInfo.getWorkPhone());
                        dto.setRemarks(orderInfo.getRemarks());
                        dto.setStartTime(orderInfo.getStartTime());
                        dto.setUserAddress(orderInfo.getUserAddress());
                        dto.setUserName(orderInfo.getUserName());
                        dto.setUserPhone(orderInfo.getUserPhone());
                        dto.setOrderState(orderInfo.getOrderState());

                        UserInfo userInfo = userInfoMapper.selectById(id);
                        // 记录日志
                        orderLogService.logUserAction("临时工查询自己订单",userInfo.getNickName(),orderInfo.getOrderId());

                        return dto;
                    } catch (Exception e) {
                        return null;
                    }
                })
                .filter(Objects::nonNull) // 过滤处理异常的订单
                .collect(Collectors.toList());
    }


    private void cancelPendingOrderMessages(String orderNumber) {
        // 这里需要实现取消未处理的延迟消息的逻辑
        // 具体实现取决于您的RabbitMQ配置和消息处理方式
        try {
            // 1. 取消所有与该订单号相关的延迟消息
            rabbitTemplate.convertAndSend(
                    RabbitMQConfig.ORDER_DELAY_QUEUE,
                    orderNumber,
                    message -> {
                        // 设置立即过期
                        message.getMessageProperties().setExpiration("0");
                        return message;
                    }
            );

            // 2. 记录日志
            System.out.println("已取消订单 {} 的所有待处理RabbitMQ消息"+ orderNumber);
        } catch (Exception e) {
            System.out.println("取消订单 {} 的RabbitMQ消息时出错: {}"+orderNumber+ e.getMessage());
        }
    }

    /**
     * 计算两个经纬度之间的距离（单位：米）
     * @param lat1 第一个点的纬度
     * @param lon1 第一个点的经度
     * @param lat2 第二个点的纬度
     * @param lon2 第二个点的经度
     * @return 两点之间的距离（单位：米）
     */
    private double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
        final int R = 6371000; // 地球半径，单位：米
        double latDistance = Math.toRadians(lat2 - lat1);
        double lonDistance = Math.toRadians(lon2 - lon1);
        double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
                + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2))
                * Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        return R * c;
    }


}
